home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Your Choice 3
/
Your Choice Software Collection 3.iso
/
prgmming
/
xlib41
/
easyx.doc
< prev
next >
Wrap
Text File
|
1994-03-25
|
26KB
|
783 lines
EASYX PROGRAMMER'S MANUAL
VERSION 1.2
(DOS Extender Library)
TechniLib Company
Copyright 1993 1994, by TechniLib (TM) Company
All Rights Reserved
TERMS OF USE AND DISTRIBUTION
XLIB is a shareware product; therefore, unregistered copies of XLIB are
made available free of charge so that potential purchasers will have the
opportunity to examine and test the software before committing payment.
Distribution of unregistered copies of XLIB to other potential users is also
permitted and appreciated. However, usage and distribution of XLIB must
conform to the following conditions. In the following statement, the term
"commercial distribution," includes shareware distribution.
1) XLIB and accompanying software must be distributed together in copies of
the original archive provided by TechniLib. Neither the archive nor
individual files therein may be modified.
2) The XLIB archive may be distributed in combination with other shareware
products; however, the XLIB archive may not be distributed with other
commercially distributed software without written consent of TechniLib.
3) Copies of XLIB which have been used to develop software for commercial
distribution must be registered before such software is marketed. Copies of
XLIB which have been used to develop noncommercial software must be registered
if such software is to be regularly used either by the developer or others.
4) Commercially distributed software must embed XLIB procedures in the
software code. Files contained in the XLIB archive may not be placed in the
distribution media.
5) XLIB is designed to offer a set of services to other executable code. XLIB
may not be used to develop software for commercial distribution which will
essentially offer any of these same services to other executable code.
Exceptions to this condition require written consent of TechniLib.
6) Rights afforded by registering a single copy of XLIB pertain only to a
single computer.
7) XLIB may be registered for a fee of $40.00 per copy. Accompany payment
with the registration form included in the XLIB archive. Registrants will be
entitled to the most recent version of the XLIB archive.
DISCLAIMER OF WARRANTY
XLIB AND ALL ACCOMPANYING SOFTWARE AND LITERATURE ARE DISTRIBUTED WITH
THE EXCLUSION OF ANY AND ALL IMPLIED WARRANTIES, AND WITH THE EXCLUSION OF
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. TechniLib
SHALL HAVE NO LIABILITY FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
RESULTING FROM THE USE OF XLIB OR ACCOMPANYING MATERIALS. The user assumes
the entire risk of using this software.
Copyright 1993 1994, by TechniLib (TM) Company
All Rights Reserved
TABLE OF CONTENTS
CHAPTERS
Page
1. Introduction 1
2. Initialization of EASYX 2
3. Memory Management 3
4. Memory-Mapped Input/Output 5
5. File Management 6
EXAMPLES
Page
1. EASYX Memory Management 4
2. EASYX File Management 9
1. Introduction
EASYX is a DOS extender library intended for programmers who are
unfamiliar with assembly language. EASYX allows real-mode high-level
languages to perform transfers between extended memory and conventional memory
or between extended memory and disk files. Many programmers need a DOS
extender merely to afford real-mode languages access to extended memory. In
such cases, EASYX is a simple and powerful alternative.
EASYX is actually little more than a real-mode interface to XLIB. The
source code for EASYX is supplied in the XLIB archive (EASYX.ASM). Assembly
language programmers may be interested in examining this code to learn more
about working with XLIB. This code has been assembled and then linked with
XLIB.LIB to create EASYX.LIB.
The EASYX library is provided in two formats - one for Microsoft
languages and the other for Borland languages. Microsoft programmers should
use EASYX.LIB. Borland programmers should use EASYXB.LIB. The respective C
header files are EASYX.H and EASYXB.H. Programmers using other languages will
have to write their own prototypes for EASYX procedures. These prototypes
should declare all EASYX procedures as far procedures conforming to the PASCAL
calling and naming convention. Prototypes for Microsoft BASIC 7.0 are
presented in the files EASYXEX1.BAS and EASYXEX2.BAS.
The programmer might prefer to use EASYXE.LIB rather than EASYX.LIB. The
former has CPU exception trapping capabilities whereas the latter does not.
EASYXE.LIB will always trap exceptions occurring in protected mode. It can
also trap real-mode exceptions provided that a DPMI 1.0 host is installed.
Borland programmers should use EASYXEB.LIB. C and C++ programmers should
continue to use EASYX.H or EASYXB.H for header files.
Most EASYX procedures can return error codes. These are always XLIB
error codes. The codes are explained in the XLIB documentation.
1
2. Initialization of EASYX
EASYX requires no initialization; however, the XLIB library which has
been linked with EASYX must be initialized before any EASYX procedures are
called. XLIB is initialized by calling INITXLIB. INITXLIB returns an error
code in DX:AX; therefore, it should be implemented as a long integer function.
The following code demonstrates initialization in Microsoft C:
extern long __far __pascal INITXLIB(void);
void main(void)
{
long errcode;
errcode = INITXLIB();
if(errcode != 0)
{
printf("Initialization error: %lX",errcode);
return;
}
.
.
.
An explanation of possible error codes is explained in the XLIB
documentation. The most common error is caused by insufficient conventional
memory. INITXLIB will attempt to allocate a small amount of conventional
memory through DOS; however, many high-level languages automatically claim all
available DOS memory, even though only a small percentage of this memory may
actually be used. The programmer must therefore release a portion of this
memory back to DOS before calling INITXLIB. This process is illustrated for
the Borland Turbo Assembler in the file EXAMP1B.ASM, and for Microsoft BASIC
in EASYXEX1.BAS. C and C++ programmers need not be concerned with this matter
because these languages allocate DOS memory dynamically.
2
3. Memory Management
High-level languages confined to real mode are incapable of addressing
extended memory; consequently, such languages must communicate with extended
memory through buffers in conventional memory. EASYX provides several
procedures to facilitate this process.
Extended memory should always be allocated with the procedure XMALLOC
before it is addressed. Attempted transfers to or from unallocated memory may
lead to page faults (exception 14), or to corruption of resident software.
XMALLOC returns a long integer error code; therefore, it should be implemented
as a long integer function. The following Microsoft C prototype shows the
structure of XMALLOC:
extern long __far __pascal XMALLOC(long nobytes, long __far *address,
long __far *size, long __far *handle);
where:
nobytes = The requested size for the extended memory block.
*address = A far pointer to a long integer variable which will receive the
linear address of the allocated block.
*size = A far pointer to a long integer variable which will receive the
actual size of the allocated extended memory block. The actual
size will always be at least as large as the requested size.
*handle = A far pointer to a long integer variable which will receive a
handle for the allocated extended memory block. The handle must
be used to release the block.
An extended memory block can be released with the XFREE procedure. XFREE
is also a long integer function which returns an error code. The C prototype
of this procedure is:
extern long __far __pascal XFREE(long handle);
where: handle = The handle assigned to the block by XMALLOC.
All extended memory is automatically released upon program termination;
consequently, XFREE will not be necessary for most programs.
Transfers between conventional memory and extended memory can be
accomplished with the MOVMEM procedure. The prototype for MOVMEM is:
extern void __far __pascal MOVMEM(long destadr, long sourceadr,long nobytes);
where:
destadr = The linear address of the destination memory.
sourceadr = The linear address of the source memory.
nobytes = The number of bytes to be transferred.
3
MOVMEM may actually be used to transfer memory between any source and
destination. The destination block and source block may also be overlapped.
MOVMEM transfers are faster than XMS or INT 15H because MOVMEM uses 32-
bit instructions. MOVMEM also exposes to less risk of losing an interrupt.
MOVMEM is a reentrant procedure, so it may be safely called within
interrupt handlers. When MOVMEM is being used in a hardware interrupt
handler, the handler should be installed after the call to INITXLIB to prevent
a call to MOVMEM before protected-mode structures have been initialized.
Real-mode programs use segment addresses instead of linear addresses.
EASYX includes a procedure called LINADR which computes linear addresses from
segment addresses. The prototype for LINADR is:
extern long __far __pascal LINADR(void __far *ptr);
The following program uses the procedures presented in this section. The
file EASYXEX1.BAS contains a Microsoft BASIC 7.0 version of the program.
Example 1: EASYX Memory Management
_____________________________________________________________________________
#include <stdio.h>
#include <easyx.h>
void main(void)
{
long errcode, nobytes, xaddress, xsize, xhandle, bufferaddress;
long buffer[1024]; /*4k buffer*/
errcode = INITXLIB(); /*Initialize XLIB*/
if(errcode != 0)
{
printf("Library initialization error: %lX\n",errcode);
return;
}
nobytes = 0x10000; /*Allocate 64k of extended memory*/
errcode = XMALLOC(nobytes, &xaddress, &xsize, &xhandle);
if(errcode != 0)
{
printf("Memory allocation error: %lX\n",errcode);
return;
}
bufferaddress = LINADR(buffer); /*Get linear address of buffer*/
MOVMEM(xaddress, bufferaddress, 4096); /*Transfer buffer to extended*/
MOVMEM(bufferaddress, xaddress, 4096); /*Transfer extended to buffer*/
errcode = XFREE(xhandle); /*Release the extended memory*/
if(errcode != 0)
printf("Memory release error: %lX\n",errcode);
}
_____________________________________________________________________________
4
4. Memory-Mapped Input/Output
On 386 and higher machines, memory reads and writes may undergo address
translation so that the address which is physically accessed may be different
from the address specified in the read/write instruction. The physically
accessed address is the "physical address." The address specified by the
read/write instruction is the "logical address." Normally programmers need
not be concerned with the difference; however, this is not the case if the
program must access an IO device which maps to a fixed physical address. In
such cases, the programmer must obtain a logical address which corresponds to
the physical address of the IO device. EASYX contains a procedure called
MAPIOMEM which will map a specified physical address into a logical address
space. MAPIOMEM is a long integer function which returns an error code. The
prototype for MAPIOMEM is:
extern long __far __pascal MAPIOMEM(long physaddress, long size,
long __far *logaddress);
where:
physaddress = The beginning physical address for the IO device.
size = The size of the physical address block in bytes.
*logaddress = A far pointer to a long integer which is to receive the assigned
logical address. Access the IO device at this address.
MAPIOMEM will sometimes return errors upon attempts to map physical
addresses in the first megabyte.
5
5. File Management
EASYX includes procedures which can transfer data between extended memory
and files. These procedures can load files to extended memory or save
extended memory to files. They can read and write files either sequentially
or randomly.
All EASYX file management routines will receive and return values in a
contiguous block of memory called a "file control block" (not to be confused
with DOS file control blocks). The file control block must be located in
conventional memory and must have the following form:
Field Name Field Type Field Description
---------- ---------- -----------------
CONDCODE DWORD Condition code from file operation
FNAME BYTE[68] File path and name (zero terminated string)
FHANDLE WORD File handle assigned by DOS
FPTRMODE WORD File pointer mode
FPTR DWORD File pointer
BLKADR DWORD Memory source/destination address
BLKSIZE DWORD Size of source/destination block in bytes
BUFADR DWORD Buffer address (conventional memory)
BUFSIZE WORD Buffer size in bytes
CONTROL WORD Control word
CONDCODE is used to return error codes. CONDCODE should be situated at
the starting address of the control block.
FNAME is a zero-terminated ASCII string defining the file path and name.
There cannot be more than 68 characters in this string, including the
termination character.
BLKADR and BLKSIZE define the source/destination memory block for the
transfer. This block may be in either conventional or extended memory.
BLKADR is a linear address.
XLIB uses DOS to access the disk. DOS cannot read or write to extended
memory; consequently, a conventional memory buffer must be set up for the DOS
transfers. File management routines shift to protected mode to perform
transfers between the buffer and the source/destination memory. BUFADR and
BUFSIZE define the conventional memory buffer. BUFADR is a linear address.
For fastest transfers, the memory block and the buffer should be DWORD
aligned and should have sizes equal to an integer multiple of four.
FPTR and FPTRMODE specify the file pointer setting to be used before
intrafile transfers to or from the disk. FPTRMODE specifies how FPTR is to be
interpreted. The following values are valid for FPTRMODE:
FPTRMODE FPTR Interpretation
-------- -------------------
0 Unsigned offset from the beginning of the file
1 Signed offset from the current file pointer
2 Signed offset from the end of the file
3 FPTR is ignored. Use current file pointer (sequential mode)
6
CONTROL is not used in the present version of EASYX. All bits in control
should be set to zero.
Since these routines perform disk operations, special precautions should
be taken to ensure that parameters in the file control block are properly
defined before performing calls. In particular, one should always make sure
that the source/destination memory block and the conventional memory buffer
are properly defined. A safe rule is to simply set the buffer size to zero
because this forces EASYX to supply a buffer when opening or creating the
file.
EASYX file routines should not be called within interrupt handlers
because all of these routines use DOS.
All EASYX file routines receive a single argument; namely, the far
address of the control block. Prototypes for the file routines are:
extern void __far __pascal XFCREATE(void __far *controlblock);
extern void __far __pascal XFOPEN(void __far *controlblock);
extern void __far __pascal XFCLOSE(void __far *controlblock);
extern void __far __pascal XFLOAD(void __far *controlblock);
extern void __far __pascal XFSAVE(void __far *controlblock);
extern void __far __pascal XFREAD(void __far *controlblock);
extern void __far __pascal XFWRITE(void __far *controlblock);
The following is a detailed explanation of each of these procedures:
XFCREATE (Create File)
Purpose: Create and open a new file of specified name in specified directory.
Control Block at Call: FNAME = file path and name.
Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
FHANDLE = file handle assigned by DOS. If the procedure is called with
BUFSIZE = 0, then EASYX will set BUFADR and BUFSIZE to its own internal
buffer.
Details:
If the file already exists, then it will be truncated to zero length.
Files created by this routine will be given both read and write access.
XFOPEN (Open File)
Purpose: Open existing file of specified name in specified directory.
Control Block at Call: FNAME = file path and name.
Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
FHANDLE = file handle assigned by DOS. If the procedure is called with
BUFSIZE = 0, then EASYX will set BUFADR and BUFSIZE to its own internal
buffer.
Details: The file is opened for both read and write access.
XFCLOSE (Close File)
Purpose: Close previously opened file.
Control Block at Call: FHANDLE = file handle.
Control Block at Return: CONDCODE = error code.
7
XFSAVE (Save File)
Purpose: Create file with contents equal to specified memory block.
Control Block at Call: FNAME = file path and name. BLKADR/BLKSIZE = address
and size of memory block to provide file contents. BUFADR/BUFSIZE = address
and size of conventional memory buffer.
Control Block at Return: CONDCODE = error code.
Details:
The file cannot already be open. The file is both created and closed by
this routine.
This routine will replace any previously existing file named FNAME.
BLKADR/BLKSIZE may define a conventional memory block provided that this
block is not overlapped by BUFADR/BUFSIZE.
If this routine is called with BUFSIZE = 0, then EASYX will automatically
supply a buffer.
XFLOAD (Load File)
Purpose: Load file contents to specified memory block.
Control Block at Call: FNAME = file path and name. BLKADR/BLKSIZE = address
and size of memory block to receive file contents. BUFADR/BUFSIZE = address
and size of conventional memory buffer.
Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
BLKSIZE = actual number of bytes transferred.
Details:
The file cannot already be open. The file is both opened and closed by
this routine.
The value of BLKSIZE as of call is interpreted as an upper limit on the
number of bytes to transfer. The entire file is loaded provided that it does
not contain more than BLKSIZE bytes.
BLKADR/BLKSIZE may define a conventional memory block provided that this
block is not overlapped by BUFADR/BUFSIZE.
If this routine is called with BUFSIZE = 0, then EASYX will automatically
supply a buffer.
XFWRITE (Write to File)
Purpose: Write specified memory block to specified location in open file.
Control Block at Call: FHANDLE = file handle. FPTR/FPTRMODE = file pointer
setting for beginning of transfer. BLKADR/BLKSIZE = address and size of
memory block to provide file contents. BUFADR/BUFSIZE = address and size of
conventional memory buffer.
Control Block at Return: CONDCODE = error code.
Details:
The file must be opened with XFOPEN or XFCREATE before using this routine.
BLKADR/BLKSIZE may define a conventional memory block provided that this
block is not overlapped by BUFADR/BUFSIZE.
Sequential transfers should set FPTRMODE = 3 for fastest execution.
XFREAD (Read From File)
Purpose: Load specified memory block from specified location in open file.
Control Block at Call: FHANDLE = file handle. FPTR/FPTRMODE = file pointer
setting for beginning of transfer. BLKADR/BLKSIZE = address and size of
memory block to receive file contents. BUFADR/BUFSIZE = address and size of
conventional memory buffer.
Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
BLKSIZE = the actual number of bytes transferred.
8
Details:
The file must be opened with XFOPEN or XFCREATE before using this routine.
BLKADR/BLKSIZE may define a conventional memory block provided that this
block is not overlapped by BUFADR/BUFSIZE.
Sequential transfers should set FPTRMODE = 3 for fastest execution.
The following C program illustrates the usage of some of the above
procedures. A BASIC translation of this program is in EASYXEX2.BAS.
Example 2: EASYX File Management
_____________________________________________________________________________
#include <stdio.h>
#include <string.h>
#include <easyx.h>
void main (void)
{
int i;
long errcode, nobytes, xaddress, xsize, handle, arrayaddress;
int array[100];
struct xfile fb; /*Declare file control block*/
errcode = INITXLIB(); /*Initialize XLIB*/
if(errcode != 0)
{
printf("Library initialization error: %lX\n",errcode);
return;
}
nobytes = 0x10000; /*Allocate 64k of extended memory*/
errcode = XMALLOC(nobytes,&xaddress,&xsize,&handle);
if(errcode != 0)
{
printf("Extended memory allocation error: %lX\n",errcode);
return;
}
for(i = 0; i < 100; i++) /*Put something in array[]*/
array[i] = i;
arrayaddress = LINADR(array); /*Compute linear address of array[]*/
9
fb.condcode = 0; /*Set control block to create file*/
strcpy(fb.fname,"junk.dat"); /*Specify file name*/
fb.blkadr = arrayaddress; /*Will transfer array[] to the file*/
fb.blksize = 200; /*There are 200 bytes in array[]*/
fb.bufsize = 0; /*Force XLIB to use its internal buffer*/
XFSAVE(&fb); /*Create file and save array[] to it*/
if(fb.condcode != 0)
{
printf("File save error: %lX\n",fb.condcode);
return;
}
XFOPEN(&fb); /*Reopen the file*/
if(fb.condcode != 0)
{
printf("File open error: %lX\n",fb.condcode);
return;
}
fb.blkadr = xaddress; /*Prepare to transfer the file to extended*/
fb.blksize = 100; /*Will transfer only 100 bytes*/
fb.fptrmode = 0; /*File pointer is relative to start of file*/
fb.fptr = 100; /*Set file pointer to 50th element*/
XFREAD(&fb); /*Read last 50 elements to extended*/
if(fb.condcode != 0)
{
printf("File read error: %lX\n",fb.condcode);
return;
}
MOVMEM(arrayaddress,xaddress,100); /*Transfer file contents back to array[]
XFCLOSE(&fb); /*Close the file*/
if(fb.condcode != 0)
{
printf("File close error: %lX\n",fb.condcode);
return;
}
errcode = XFREE(handle); /*Release extended memory*/
if(errcode != 0)
{
printf("Memory release error: %lX\n",errcode);
return;
}
}
_____________________________________________________________________________
10